package com.geekteam.manga.provider;



import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.geekteam.manga.Utils.LogUtils;
import com.geekteam.manga.Utils.SelectionBuilder;
import com.geekteam.manga.provider.MangaContract.ContentManga;
import com.geekteam.manga.provider.MangaContract.Manga;
import com.geekteam.manga.provider.MangaContract.MangaChap;
import com.geekteam.manga.provider.MangaContract.RecentManga;
import com.geekteam.manga.provider.MangaDatabase.Tables;


import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

public class MangaProvider extends ContentProvider{
	
	private static final String TAG = LogUtils.makeLogTag(MangaProvider.class);
	private MangaDatabase mOpenHelper;
	private static final UriMatcher sUriMatcher = buildUriMatcher();

	private static final int MANGA = 100;
	private static final int MANGA_ID = 101;
	private static final int MANGACHAP = 200;
	private static final int MANGACHAP_ID = 201;
	private static final int MANGACHAP_CHAPID = 202;
	private static final int RECENTMANGA = 300;
	private static final int RECENTMANGA_ID = 301;
	private static final int CONTENTMANGA = 400;
	private static final int CONTENTMANGA_ID = 401;
	private static final int CONTENTMANGA_CHAPID = 402;

	private static final int SEARCH_SUGGEST = 800;

	private static UriMatcher buildUriMatcher() {
		final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
		final String authority = MangaContract.CONTENT_AUTHORITY;

		matcher.addURI(authority, "manga", MANGA);
		matcher.addURI(authority, "manga/*", MANGA_ID);
		matcher.addURI(authority, "mangachap", MANGACHAP);
		matcher.addURI(authority, "mangachap/*", MANGACHAP_ID);
		matcher.addURI(authority, "mangachap/*", MANGACHAP_CHAPID);
		matcher.addURI(authority, "recentmanga/", RECENTMANGA);
		matcher.addURI(authority, "recentmanga/*", RECENTMANGA_ID);
		matcher.addURI(authority, "contentmanga/", CONTENTMANGA);
		matcher.addURI(authority, "contentmanga/*", CONTENTMANGA_ID);
		matcher.addURI(authority, "contentmanga/*", CONTENTMANGA_CHAPID);

		return matcher;
	}

	@Override
	public boolean onCreate() {
		mOpenHelper = new MangaDatabase(getContext());
		mOpenHelper.getWritableDatabase();
		return true;
	}

	@Override
	public String getType(Uri uri) {
		final int match = sUriMatcher.match(uri);
		switch (match) {
		case MANGA:
			return Manga.CONTENT_TYPE;
		case MANGA_ID:
			return Manga.CONTENT_ITEM_TYPE;
		case RECENTMANGA:
			return RecentManga.CONTENT_TYPE;
		case RECENTMANGA_ID:
			return RecentManga.CONTENT_ITEM_TYPE;
		case MANGACHAP:
			return MangaChap.CONTENT_TYPE;
		case MANGACHAP_ID:
			return MangaChap.CONTENT_ITEM_TYPE;
		case MANGACHAP_CHAPID:
			return MangaChap.CONTENT_ITEM_TYPE;
		case CONTENTMANGA:
			return ContentManga.CONTENT_TYPE;
		case CONTENTMANGA_ID:
			return ContentManga.CONTENT_ITEM_TYPE;
		case CONTENTMANGA_CHAPID:
			return ContentManga.CONTENT_ITEM_TYPE;
		default:
			throw new UnsupportedOperationException("Unknown uri: " + uri);
		}
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		com.geekteam.manga.Utils.LogUtils.LOGV(TAG, "delete(uri=" + uri + ")");
		if (uri == MangaContract.BASE_CONTENT_URI) {
			deleteDatabase();
			getContext().getContentResolver().notifyChange(uri, null, false);
			return 1;
		}
		final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		final SelectionBuilder builder = buildSimpleSelection(uri);
		int retVal = builder.where(selection, selectionArgs).delete(db);
		getContext().getContentResolver().notifyChange(uri, null,
				!MangaContract.hasCallerIsSyncAdapterParameter(uri));
		return retVal;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		com.geekteam.manga.Utils.LogUtils.LOGV(TAG, "insert(uri=" + uri + ", values=" + values.toString() + ")");
		final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		final int match = sUriMatcher.match(uri);
		boolean syncToNetwork = !MangaContract
				.hasCallerIsSyncAdapterParameter(uri);
		switch (match) {
		case MANGA:
			db.insertOrThrow(Tables.MANGA, null, values);
			getContext().getContentResolver().notifyChange(uri, null,
					syncToNetwork);
		case RECENTMANGA:
			db.insertOrThrow(Tables.RECENTMANGA, null, values);
			getContext().getContentResolver().notifyChange(uri, null,
					syncToNetwork);
		case MANGACHAP:
			db.insertOrThrow(Tables.MANGACHAP, null, values);
			getContext().getContentResolver().notifyChange(uri, null,
					syncToNetwork);
		case CONTENTMANGA:
			db.insertOrThrow(Tables.CONTENTMANGA, null, values);
			getContext().getContentResolver().notifyChange(uri, null,
					syncToNetwork);
		}
		return null;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		com.geekteam.manga.Utils.LogUtils.LOGV(TAG, "query(uri=" + uri + ", proj=" + Arrays.toString(projection)
				+ ")");
		final SQLiteDatabase db = mOpenHelper.getReadableDatabase();

		final int match = sUriMatcher.match(uri);
		switch (match) {
		default:
			final SelectionBuilder builder = buildExpandedSelection(uri, match);
			return builder.where(selection, selectionArgs).query(db,
					projection, sortOrder);
		case SEARCH_SUGGEST:// search query here
			return null;
		}
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		com.geekteam.manga.Utils.LogUtils.LOGV(TAG, "update(uri=" + uri + ", values=" + values.toString() + ")");
		final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		final SelectionBuilder builder = buildSimpleSelection(uri);
		int retVal = builder.where(selection, selectionArgs).update(db, values);
		boolean syncToNetwork = !MangaContract
				.hasCallerIsSyncAdapterParameter(uri);
		getContext().getContentResolver()
				.notifyChange(uri, null, syncToNetwork);
		return retVal;
	}

	@Override
	public ContentProviderResult[] applyBatch(
			ArrayList<ContentProviderOperation> operations)
			throws OperationApplicationException {
		final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		db.beginTransaction();
		try {
			final int numOperations = operations.size();
			final ContentProviderResult[] results = new ContentProviderResult[numOperations];
			for (int i = 0; i < numOperations; i++) {
				results[i] = operations.get(i).apply(this, results, i);
			}
			db.setTransactionSuccessful();
			return results;
		} finally {
			db.endTransaction();
		}
	}

	private void deleteDatabase() {
		mOpenHelper.close();
		Context context = getContext();
		MangaDatabase.deleteDatabase(context);
		mOpenHelper = new MangaDatabase(getContext());
	}

	private SelectionBuilder buildExpandedSelection(Uri uri, int match) {
		final SelectionBuilder builder = new SelectionBuilder();
		switch (match) {
		case MANGA:
			return builder.table(Tables.MANGA);
		case MANGA_ID:
			final String mangaId = Manga.getMangaId(uri);
			return builder.table(Tables.MANGA)
					.where(Manga.MANGA_ID+"=?", mangaId);
		case RECENTMANGA:
			final List<String> segments = uri.getPathSegments();
            final String startId = segments.get(2);
            final String endId = segments.get(3);
            return builder.table(Tables.RECENTMANGA)
            		.where(RecentManga.MANGA_ID+">=?", startId)
            		.where(RecentManga.MANGA_ID+"<=?", endId);
		case RECENTMANGA_ID:
			final String recentMangaId = RecentManga.getRecentMangaId(uri);
			return builder.table(Tables.RECENTMANGA)
					.where(RecentManga.MANGA_ID+"=?", recentMangaId);
		case MANGACHAP:
			return builder.table(Tables.MANGACHAP);
//		case MANGACHAP_ID:
//			final String recentMangaId = RecentManga.getRecentMangaId(uri);
//			return builder.table(Tables.RECENTMANGA)
//					.where(RecentManga.RECENTMANGA_ID+"=?", recentMangaId);
		case CONTENTMANGA:
			final List<String> citySegments = uri.getPathSegments();
            final String startCityId = citySegments.get(2);
            final String endCityId = citySegments.get(3);
            return builder.table(Tables.CONTENTMANGA)
            		.where(ContentManga.MANGA_ID+">=?", startCityId)
            		.where(ContentManga.MANGA_ID+"<=?", endCityId);
		}
		return builder;
	}

	private SelectionBuilder buildSimpleSelection(Uri uri) {
		final SelectionBuilder builder = new SelectionBuilder();
		final int match = sUriMatcher.match(uri);
		switch (match) {
		case MANGA:
			return builder.table(Tables.MANGA);
		case MANGA_ID:
			final String mangaId = Manga.getMangaId(uri);
			com.geekteam.manga.Utils.LogUtils.LOGV(TAG, "mangaID: " + mangaId);
			return builder.table(Tables.MANGA).where(Manga.MANGA_ID + "=?", mangaId);
		case RECENTMANGA:
			return builder.table(Tables.RECENTMANGA);
		case RECENTMANGA_ID:
			String recentMangaId = RecentManga.getRecentMangaId(uri);
			com.geekteam.manga.Utils.LogUtils.LOGV(TAG, "recentMangaID: " + recentMangaId);
			return builder.table(Tables.RECENTMANGA).where(
					RecentManga.MANGA_ID + "=?", recentMangaId);
		case MANGACHAP:
			return builder.table(Tables.MANGACHAP);
		case MANGACHAP_ID:
			String mangaChapId = MangaChap.getMangaChapId(uri);
			com.geekteam.manga.Utils.LogUtils.LOGV(TAG, "mangaChapID: " + mangaChapId);
			return builder.table(Tables.MANGACHAP)
					.where(MangaChap.MANGA_ID + "=?", mangaChapId);
		case CONTENTMANGA:
			return builder.table(Tables.CONTENTMANGA);
		case CONTENTMANGA_ID:
			String contentMangaId = ContentManga.getContentMangaId(uri);
			com.geekteam.manga.Utils.LogUtils.LOGV(TAG, "contentMangaId: " + contentMangaId);
			return builder.table(Tables.CONTENTMANGA)
					.where(ContentManga.MANGA_ID + "=?", contentMangaId);
		default:
			throw new UnsupportedOperationException("Unknown uri: " + uri);
		}
	}

}
